package com.ruoyi.pyo.wechat.tools;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.pyo.wechat.body.resp.AccessTokenRespBody;
import com.ruoyi.pyo.wechat.body.resp.Code2SessionRespBody;
import com.ruoyi.pyo.wechat.body.resp.UserPhoneNumberRespBody;
import com.ruoyi.pyo.wechat.cache.WeChatCacheTemplate;
import com.ruoyi.pyo.wechat.config.WeChatProps;
import com.ruoyi.pyo.wechat.exception.WeChatException;
import okhttp3.*;
import org.springframework.http.HttpEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

public class WeChatTools {
    private final static String ACCESSTOKEN_CACHE_KEY = "wechat:accessToken";
    /**
     * 请求参数
     * 属性	类型	默认值	必填	说明
     * appid	string		是	小程序 appId
     * secret	string		是	小程序 appSecret
     * js_code	string		是	登录时获取的 code
     * grant_type	string		是	授权类型，此处只需填写 authorization_cod
     * <p>
     * 返回值：
     * <p>
     * 属性	类型	说明
     * openid	string	用户唯一标识
     * session_key	string	会话密钥
     * unionid	string	用户在开放平台的唯一标识符，若当前小程序已绑定到微信开放平台帐号下会返回，详见 UnionID 机制说明。
     * errcode	number	错误码
     * errmsg	string	错误信息
     */
    private static final String JSCODE_2_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
    /**
     * 与ACCESS_TOKEN_URL比较是每次获取的都是当前已存在最新的，而不会重新颁发
     */
    private static final String ACCESS_STABLE_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/stable_token";
    private static final String GET_USER_PHONE_NUMBER_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={0}";
    private static final String MSG_CHECK = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token={0}";

    private static final String DRIVING = "https://api.weixin.qq.com/cv/ocr/driving?access_token={0}";
    private static final String DRIVING_LICENSE = "https://api.weixin.qq.com/cv/ocr/drivinglicense?access_token={0}";


    private final RestTemplate wxRestTemplate;
    private final WeChatProps weChatProps;
    private final WeChatCacheTemplate weChatCacheTemplate;

    public WeChatTools(RestTemplate wxRestTemplate, WeChatProps weChatProps, WeChatCacheTemplate weChatCacheTemplate) {
        this.wxRestTemplate = wxRestTemplate;
        this.weChatCacheTemplate = weChatCacheTemplate;
        this.weChatProps = weChatProps;
    }


    /**
     * @param jsCode jsCode
     * @return Code2SessionRespBody
     */
    public Code2SessionRespBody jscode2session(String jsCode) {
        String requestUrl = MessageFormat.format(JSCODE_2_SESSION_URL, weChatProps.getAppId(), weChatProps.getSecret(), jsCode);
        String respBody = wxRestTemplate.getForEntity(requestUrl, String.class).getBody();
        Code2SessionRespBody code2SessionRespBody = WeChatJsonUtils.parseObject(respBody, Code2SessionRespBody.class);
        // 判断有误异常
        if (StringUtils.hasLength(code2SessionRespBody.getErrorMsg())) {
            // 抛出错误
            throw new WeChatException(code2SessionRespBody.getErrorCode() + ":" + code2SessionRespBody.getErrorMsg());
        }
        return code2SessionRespBody;
    }


    /**
     * 获取用户手机号
     *
     * @param code code
     * @return UserPhoneNumberRespBody
     */
    public UserPhoneNumberRespBody getUserPhoneNumber(String code) {
        Map<String, String> requestBody = new HashMap<>(1);
        requestBody.put("code", code);
        HttpEntity<String> entity = new HttpEntity<>(JSONUtil.toJsonStr(requestBody));
        String requestUrl = MessageFormat.format(GET_USER_PHONE_NUMBER_URL, getAccessToken(weChatProps));
        String respBody = wxRestTemplate.postForEntity(requestUrl, entity, String.class).getBody();
        UserPhoneNumberRespBody userPhoneNumberRespBody = WeChatJsonUtils.parseObject(respBody, UserPhoneNumberRespBody.class);
        // 判断有误异常
        if (!"ok".equals(userPhoneNumberRespBody.getErrorMsg())) {
            // 抛出错误
            throw new WeChatException(userPhoneNumberRespBody.getErrorCode() + ":" + userPhoneNumberRespBody.getErrorMsg());
        }
        return userPhoneNumberRespBody;
    }

    /**
     * @param weChatProps wxProps
     * @return token
     */
    public String getAccessToken(WeChatProps weChatProps) {
        String accessToken = weChatCacheTemplate.getValue(ACCESSTOKEN_CACHE_KEY);
        if (StringUtils.hasLength(accessToken)) {
            return accessToken;
        }
        Map<String, String> requestBody = new HashMap<>(3);
        requestBody.put("grant_type", "client_credential");
        requestBody.put("appid", weChatProps.getAppId());
        requestBody.put("secret", weChatProps.getSecret());
        HttpEntity<String> entity = new HttpEntity<>(JSONUtil.toJsonStr(requestBody));
        RestTemplate restTemplate = new RestTemplate();
        String respBody = restTemplate.postForObject(ACCESS_STABLE_TOKEN_URL, entity, String.class);
        System.out.println(respBody);
        AccessTokenRespBody accessTokenRespBody = WeChatJsonUtils.parseObject(respBody, AccessTokenRespBody.class);
        // 判断有误异常
        if (StringUtils.hasLength(accessTokenRespBody.getErrorMsg())) {
            // 抛出错误
            throw new WeChatException(accessTokenRespBody.getErrorCode() + ":" + accessTokenRespBody.getErrorMsg());
        }
        weChatCacheTemplate.setValue(ACCESSTOKEN_CACHE_KEY, accessTokenRespBody.getAccessToken(), 7000);
        return accessTokenRespBody.getAccessToken();
    }
}
